package cn.dvptech.remotemate.ui.activity

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.BitmapFactory
import android.graphics.Color
import android.net.wifi.WifiManager
import android.view.Gravity
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.View
import android.view.ViewGroup
import android.webkit.ValueCallback
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.appcompat.widget.ContentFrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
import cn.bingoogolapple.qrcode.core.BGAQRCodeUtil
import cn.bingoogolapple.qrcode.zxing.QRCodeEncoder
import cn.dvptech.remotemate.R
import cn.dvptech.remotemate.aop.Log
import cn.dvptech.remotemate.aop.SingleClick
import cn.dvptech.remotemate.app.AppActivity
import cn.dvptech.remotemate.other.DensityUtil
import cn.dvptech.remotemate.other.SupportMultipleScreensUtil
import cn.dvptech.remotemate.screenmirror.decode.DecodeThread
import cn.dvptech.remotemate.screenmirror.decode.VideoMediaCodec
import cn.dvptech.remotemate.screenmirror.listener.OnConnectionStateChangeListener
import cn.dvptech.remotemate.screenmirror.listener.OnFrameReceivedListener
import cn.dvptech.remotemate.screenmirror.screenHelper.Constant
import cn.dvptech.remotemate.screenmirror.screenHelper.Frame
import cn.dvptech.remotemate.screenmirror.server.NormalPlayQueue
import cn.dvptech.remotemate.screenmirror.server.TcpServer
import cn.dvptech.remotemate.widget.ControllerLayout
import com.blankj.utilcode.util.BarUtils
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.ScreenUtils
import com.blankj.utilcode.util.ThreadUtils
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import org.json.JSONObject
import timber.log.Timber
import java.util.Formatter


/**
 *    author  : ulongx
 *    website : www.dvptech.cn
 *    date    : 2024/6/24
 *    desc    :
 */
class MainActivity : AppActivity() {

    override fun getLayoutId(): Int = R.layout.activity_master

    private val deviceInfo: LinearLayout? by lazy { findViewById(R.id.device_info) }

    private var isFabOpen = false
    private val fabMain: FloatingActionButton? by lazy { findViewById(R.id.fabMain) }
    private val fabOptionBack: FloatingActionButton? by lazy { findViewById(R.id.fabOptionBack) }
    private val fabOptionHome: FloatingActionButton? by lazy { findViewById(R.id.fabOptionHome) }
    private val fabOptionApps: FloatingActionButton? by lazy { findViewById(R.id.fabOptionApps) }
    private val fabOptionNotifications: FloatingActionButton? by lazy { findViewById(R.id.fabOptionNotifications) }
    private val qrcodeImg: ImageView? by lazy { findViewById(R.id.iv_network_logo) }
    private val localIpTV: TextView? by lazy { findViewById(R.id.iv_network_ip) }
    private val tvLog: TextView? by lazy { findViewById(R.id.tv_log) }

    private var localIP: String? = null

    private val controllerLayout: ControllerLayout? by lazy { findViewById(R.id.ma_controller_layout) }
    private val mSurface: SurfaceView? by lazy { findViewById(R.id.ma_sv_screen) }

    //服务连接回调
    var valueCallback: ValueCallback<Boolean>? = null

    private var mSurfaceHolder: SurfaceHolder? = null
    private var mDecodeThread: DecodeThread? = null

    private var mPlayqueue: NormalPlayQueue? = null
    private var tcpServer: TcpServer? = null
    private var videoMediaCodec: VideoMediaCodec? = null


    override fun initView() {

        setOnClickListener(fabMain, fabOptionBack, fabOptionHome, fabOptionApps, fabOptionNotifications)

        Timber.d("Pad ---> screenWidth: ${ScreenUtils.getScreenWidth()} , screenHeight: ${ScreenUtils.getScreenHeight()}")

//        // 初始化surfaceView
        getContentView()!!.viewTreeObserver.addOnDrawListener {
            //添加视频画面修改监听，计算宽高比，方面后面手势坐标的计算
            val svScreenWidth = controllerLayout!!.measuredWidth
            val svScreenHeight = controllerLayout!!.measuredHeight

            if (svScreenWidth == 0 || targetScreenWidth == 0) return@addOnDrawListener
            dimensionRatioX = svScreenWidth.toFloat() / targetScreenWidth
            dimensionRatioY = svScreenHeight.toFloat() / targetScreenHeight
        }

        mSurfaceHolder = mSurface!!.holder
        mSurfaceHolder?.addCallback(object : SurfaceHolder.Callback {
            override fun surfaceCreated(holder: SurfaceHolder) {
                initialMediaCodec(holder)
            }

            override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {}
            override fun surfaceDestroyed(holder: SurfaceHolder) {
                videoMediaCodec?.release()
            }
        })
    }

    private fun initialMediaCodec(holder: SurfaceHolder) {
//        val dm = resources.displayMetrics
        videoMediaCodec = VideoMediaCodec(holder, Constant.header_sps, Constant.header_pps)
            .setMimeType(Constant.MIME_TYPE)
            .setFrameInternal(Constant.KEY_I_FRAME_INTERVAL)
            .setFrameRate(Constant.KEY_FRAME_RATE)
            .setVideoBit(Constant.KEY_BIT_RATE)
            .setVideoFPS(Constant.VIDEO_FPS)
//            .setScreenHeight(dm.heightPixels)
//            .setScreenWidth(dm.widthPixels)
            .build()
        videoMediaCodec?.start()
        mDecodeThread = DecodeThread(videoMediaCodec?.codec, mPlayqueue)
        mDecodeThread?.start()
    }

    private fun startServer() {
        mPlayqueue = NormalPlayQueue()
        tcpServer = TcpServer()
        tcpServer?.setOnAccepttBuffListener(MyAcceptH264Listener())
        tcpServer?.setOnTcpConnectListener(MyAcceptTcpStateListener())
        tcpServer?.startServer()
    }

    //接收到H264buff的回调
    inner class MyAcceptH264Listener : OnFrameReceivedListener {
        override fun acceptBuff(frame: Frame?) {
            mPlayqueue?.putByte(frame)
        }

        override fun acceptString(message: String) {
            Timber.tag("MainActivity").i("acceptString: $message")
            val jsonObject = JSONObject(message)
            val type = jsonObject.optString("type")
            //录制端屏幕宽高响应
            if ("GET_SCREEN_RESPONSE" == type) {
                val data = jsonObject.optJSONObject("data")
                data?.let {
                    targetScreenWidth = it.optInt("screenWidth")
                    targetScreenHeight = it.optInt("screenHeight")
                    controllerLayout?.tcpServer = tcpServer
                    valueCallback?.onReceiveValue(true)
                    val orientationType = jsonObject.optInt("orientation")
                    changeSurfaceState(targetScreenWidth, targetScreenHeight, orientationType)
                }
            }
        }
    }

    var targetOrientation: Int = Configuration.ORIENTATION_UNDEFINED
    var targetWidth = 0
    var targetHeight = 0

    /**
     *  视频屏幕大小
     */
    private fun changeSurfaceState(targetWidth: Int, targetHeight: Int, targetOrientation: Int) {
        ThreadUtils.runOnUiThread {
            this.targetOrientation = targetOrientation
            this.targetWidth = targetWidth
            this.targetHeight = targetHeight
            val layoutParams = mSurface?.layoutParams as FrameLayout.LayoutParams?
            layoutParams?.width = ScreenUtils.getAppScreenWidth()
            layoutParams?.height = ScreenUtils.getAppScreenHeight()

            //判断是否横屏
            if (getResources().configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                //当前设备横屏
                if (targetOrientation == Configuration.ORIENTATION_LANDSCAPE) {

                    var targetWh = targetWidth / targetHeight.toFloat()
                    val newWidth = ScreenUtils.getAppScreenWidth()+BarUtils.getStatusBarHeight()
                    val newHeight = (newWidth * targetWh).toInt()
                    layoutParams?.width = newWidth
                    layoutParams?.height = newHeight

                    tvLog?.append("当前设备：横屏，宽=${ScreenUtils.getAppScreenWidth()},高=${ScreenUtils.getScreenHeight()}\n")
                    tvLog?.append("显示宽高：${if (targetOrientation == 1) "竖屏" else "横屏"}，宽=${(newWidth).toInt()},高=${newHeight}\n")

                } else {

                    var targetWh = targetWidth / targetHeight.toFloat()
                    val newHeight = ScreenUtils.getAppScreenHeight()
                    val newWidth = (newHeight * targetWh).toInt()
                    layoutParams?.width = newWidth
                    layoutParams?.height = newHeight

                    tvLog?.append("当前设备：横屏，宽=${ScreenUtils.getAppScreenWidth()},高=${ScreenUtils.getScreenHeight()}\n")
                    tvLog?.append("显示宽高：${if (targetOrientation == 1) "竖屏" else "横屏"}，宽=${(newWidth).toInt()},高=${newHeight}\n")

                }

            } else {
                //当前设备竖屏
                var targetWh = targetWidth / targetHeight.toFloat()
                if (targetOrientation == Configuration.ORIENTATION_LANDSCAPE) {
                    //对方是横屏
                    val newWidth = ScreenUtils.getAppScreenWidth()
                    layoutParams?.width = newWidth
                    layoutParams?.height = (newWidth * targetWh).toInt()
                } else {
                    val appScreenHeight = ScreenUtils.getAppScreenHeight() + BarUtils.getStatusBarHeight()
                    layoutParams?.width = (appScreenHeight * targetWh).toInt()
                    layoutParams?.height = appScreenHeight
                    tvLog?.append("当前设备：竖屏，宽=${ScreenUtils.getAppScreenWidth()}, 高=${ScreenUtils.getAppScreenHeight()}\n")
                    tvLog?.append("显示宽高：宽=${(appScreenHeight * targetWh).toInt()}, 高=${appScreenHeight}\n")
                }


            }
            tvLog?.append("目标设备：${if (targetOrientation == 1) "竖屏" else "横屏"}，宽=${targetWidth},高=${targetHeight}\n")
            mSurface?.layoutParams = layoutParams
            mSurface?.requestLayout()

            //设置视频画面宽高比与被控端宽高比一致
            val clParams = controllerLayout?.layoutParams as FrameLayout.LayoutParams?
            //判断是否横屏
            if (getResources().configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {

                if (targetOrientation == Configuration.ORIENTATION_LANDSCAPE) {

                    val targetWh = targetWidth / targetHeight.toFloat()
                    val newWidth = ScreenUtils.getAppScreenWidth()+BarUtils.getStatusBarHeight()
                    val newHeight = (newWidth / targetWh).toInt()
                    clParams?.width = newWidth
                    clParams?.height = newHeight

                } else {

                    val targetWh = targetWidth / targetHeight.toFloat()
                    val newWidth = (ScreenUtils.getAppScreenHeight() * targetWh).toInt()
                    val newHeight = ScreenUtils.getAppScreenHeight()
                    clParams?.width = newWidth
                    clParams?.height = newHeight
                }
            } else {
                // 当前是竖屏
                val targetWh = targetWidth / targetHeight.toFloat()
                if (targetOrientation == Configuration.ORIENTATION_LANDSCAPE) {
                    val newWidth = ScreenUtils.getAppScreenWidth()

                    clParams?.width = newWidth
                    clParams?.height = (newWidth / targetWh).toInt()
                } else {

                    val appScreenHeight = ScreenUtils.getAppScreenHeight() + BarUtils.getStatusBarHeight()
                    clParams?.width = (appScreenHeight * targetWh).toInt()
                    clParams?.height = appScreenHeight
                }
            }


//            clParams?.addRule(RelativeLayout.CENTER_IN_PARENT)
            controllerLayout?.layoutParams = clParams
            controllerLayout?.requestLayout()
//            SupportMultipleScreensUtil.scaleViewSize(controllerLayout)

//            controllerLayout?.requestLayout()

        }
    }

    //客户端Tcp连接状态的回调...
    inner class MyAcceptTcpStateListener : OnConnectionStateChangeListener {
        override fun acceptTcpConnect() {    //接收到客户端的连接...
            Timber.d("accept a tcp connect...")
            ThreadUtils.runOnUiThread {
                deviceInfo?.visibility = View.GONE
                controllerLayout?.visibility = View.VISIBLE
                mSurface?.visibility = View.VISIBLE

            }
            //服务连接成功后先获取被控端屏幕宽高
            tcpServer?.sendMessage(JSONObject().apply {
                put("type", "GET_SCREEN")
            }.toString())
        }

        override fun acceptTcpDisConnect(e: Exception) {  //客户端的连接断开...
            Timber.d("acceptTcpConnect exception = $e")
            ThreadUtils.runOnUiThread {
                deviceInfo?.visibility = View.VISIBLE
                controllerLayout?.visibility = View.GONE
                mSurface?.visibility = View.GONE
            }
            mDecodeThread?.shutdown()

        }
    }


    override fun initData() {
//        sendMessageToClient("Your message here")
        localIP = getLocalIpAddress()
        Timber.d("getLocalIpAddress  ------------------> $localIP")
        XXPermissions.with(this)
            .permission(Permission.ACCESS_FINE_LOCATION)
            .permission(Permission.WRITE_EXTERNAL_STORAGE)
            .request(object : OnPermissionCallback {

                override fun onGranted(permissions: MutableList<String>, allGranted: Boolean) {
                    if (!allGranted) {
                        toast("获取部分权限成功，但部分权限未正常授予")
                        return
                    }
                    Timber.d("获取权限成功")
                    startServer()
                }

                override fun onDenied(permissions: MutableList<String>, doNotAskAgain: Boolean) {
                    if (doNotAskAgain) {
                        toast("被永久拒绝授权，请手动授予权限")
                        // 如果是被永久拒绝就跳转到应用权限系统设置页面
                        XXPermissions.startPermissionActivity(getContext(), permissions)
                    } else {
                        toast("获取权限失败")
                    }
                }
            })

//        lifecycleScope.launch {
        ThreadUtils.runOnUiThread {
            val logoBitmap = BitmapFactory.decodeResource(
                this@MainActivity.getResources(),
                R.mipmap.ic_launcher
            )
            val qrCode = QRCodeEncoder.syncEncodeQRCode(
                localIP,
                BGAQRCodeUtil.dp2px(this@MainActivity, 150f),
                Color.BLACK, Color.WHITE,
                logoBitmap
            )

            qrcodeImg?.setImageBitmap(qrCode)
            localIpTV?.text = localIP

            Timber.d("MainActivity initData")
        }
//        }
    }


    override fun onStop() {
        super.onStop()
        // 应用退到后台，会调用次方法
    }

    @SingleClick
    override fun onClick(view: View) {
        when (view) {
            fabMain -> {
                Timber.d("fabMainfabMainfabMainfabMainfabMainfabMainfabMain clicks~~~")
                if (isFabOpen) {
                    closeFabMenu()
                } else {
                    openFabMenu()
                }
            }
//            fabOptionSendFile -> {
//                // 发送文件
//            }
//            fabOptionConnState -> {
//                // 连接状态
//            }
            fabOptionBack -> {
                Timber.d("fabOptionBack clicks~~~")
                //发送返回事件
                tcpServer?.sendMessage(GsonUtils.toJson(hashMapOf<String, Any>().apply {
                    put("type", "BACK")
                }))
            }

            fabOptionHome -> {
                //首页事件
                tcpServer?.sendMessage(GsonUtils.toJson(hashMapOf<String, Any>().apply {
                    put("type", "HOME")
                }))
            }

            fabOptionApps -> {
                //最近任务
                tcpServer?.sendMessage(GsonUtils.toJson(hashMapOf<String, Any>().apply {
                    put("type", "TASKS")
                }))
            }

            fabOptionNotifications -> {
                //通知
                tcpServer?.sendMessage(GsonUtils.toJson(hashMapOf<String, Any>().apply {
                    put("type", "NOTIFICATIONS")
                }))
            }
        }
    }

    @SuppressLint("WrongConstant")
    override fun onResume() {
        super.onResume()
    }

    override fun onPause() {
        super.onPause()
    }

    private fun getLocalIpAddress(): String {
        val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
        val wifiInfo = wifiManager.connectionInfo
        val ipAddress = wifiInfo.ipAddress
        return Formatter().format(
            "%d.%d.%d.%d",
            (ipAddress and 0xff),
            (ipAddress shr 8 and 0xff),
            (ipAddress shr 16 and 0xff),
            (ipAddress shr 24 and 0xff)
        ).toString()
    }

    private fun openFabMenu() {
        isFabOpen = true
//        fabOptionSendFile?.visibility = View.VISIBLE
//        fabOptionConnState?.visibility = View.VISIBLE
        fabOptionBack?.visibility = View.VISIBLE
        fabOptionHome?.visibility = View.VISIBLE
        fabOptionApps?.visibility = View.VISIBLE
        fabOptionNotifications?.visibility = View.VISIBLE

    }

    private fun closeFabMenu() {
        isFabOpen = false
//        fabOptionSendFile?.visibility = View.INVISIBLE
//        fabOptionConnState?.visibility = View.INVISIBLE
        fabOptionBack?.visibility = View.INVISIBLE
        fabOptionHome?.visibility = View.INVISIBLE
        fabOptionApps?.visibility = View.INVISIBLE
        fabOptionNotifications?.visibility = View.INVISIBLE
    }

    override fun onDestroy() {
        tcpServer?.stopServer()
        super.onDestroy()
    }

    companion object {

        //视频流画面宽高
//        var svScreenWidth = 0
//        var svScreenHeight = 0

        //被控端屏幕宽高
        var targetScreenWidth = 0
        var targetScreenHeight = 0

        //画面宽高与被控屏幕宽高比，svScreenWidth / targetScreenWidth
        var dimensionRatioX = 0F
        var dimensionRatioY = 0F

        @Log
        fun start(context: Context) {
            val intent = Intent(context, MainActivity::class.java)
            if (context !is Activity) {
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            }
            context.startActivity(intent)
        }
    }

    override fun finish() {
        super.finish()
        if (mPlayqueue != null) {
            mPlayqueue!!.stop()
        }
        if (videoMediaCodec != null) {
            videoMediaCodec!!.release()
        }
        if (mDecodeThread != null) {
            mDecodeThread!!.shutdown()
        }
        if (tcpServer != null) {
            tcpServer!!.stopServer()
        }
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        changeSurfaceState(targetScreenWidth, targetScreenHeight, targetOrientation)
    }
}